package com.jinznet.transit.wx;

import java.io.IOException;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.LoadingCache;

public class HttpClientUtil {
    /** 
    * 最大连接数
    */  
   private static int MAX_CONNECTION_NUM = 50;
 
 
   /** 
    * 单路由最大连接数
    */  
   private static int MAX_PER_ROUTE = 20;  
 
 
   /** 
    * 向服务端请求超时时间设置(单位:毫秒) 
    */  
   private static int SERVER_REQUEST_TIME_OUT = 2000;  
 
 
   /** 
    * 服务端响应超时时间设置(单位:毫秒) 
    */  
   private static int SERVER_RESPONSE_TIME_OUT = 2000;  
   
   
   public LoadingCache<String, String> htmlCache = null;
   
   private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
   
   private static PoolingHttpClientConnectionManager clientConnectionManager=null;
   private static CloseableHttpClient httpClient=null;
   private final static Object syncLock = new Object();
   
   public static final String CHARSET_UTF8 = "UTF-8";
   
   static {
       initConnectionManager();
   }
   
   private static void initConnectionManager() {  
       try {
           
           // 创建SSLContext对象，并使用我们指定的信任管理器初始化
           TrustManager[] tm = { new MyX509TrustManager() };
           SSLContext sslContext = SSLContext.getInstance("TLS", "SunJSSE");
           sslContext.init(null, tm, new java.security.SecureRandom());
           //SSLSocketFactory ssl = sslContext.getSocketFactory();
           SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
           
           ConnectionSocketFactory plainsf = PlainConnectionSocketFactory
                   .getSocketFactory();
           
           Registry<ConnectionSocketFactory> registry = RegistryBuilder
                   .<ConnectionSocketFactory> create().register("http", plainsf)
                   .register("https", sslsf).build();
           
           clientConnectionManager = new PoolingHttpClientConnectionManager(registry);
           clientConnectionManager.setMaxTotal(MAX_CONNECTION_NUM);
           clientConnectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
       } catch(Exception e) {
           logger.error("initConnectionManager Exception ", e);
       }

   }  
   
   public static CloseableHttpClient getHttpClient(){
       if(httpClient == null){
           synchronized (syncLock){
               if(httpClient == null){

                   RequestConfig requestConfig = RequestConfig.custom()
                           .setSocketTimeout(SERVER_REQUEST_TIME_OUT)
                           .setConnectTimeout(SERVER_RESPONSE_TIME_OUT)
                           .build(); 
                   
                   httpClient = HttpClients.custom()
                           .setConnectionManager(clientConnectionManager)
                           .setDefaultRequestConfig(requestConfig)
                           .build();
               
               }
           }
       }
       return httpClient;
   }
   
   
   public static String post(String url, Map<String, String> postMap) {
       String postJson = JSONObject.toJSONString(postMap);
       return post(url, postJson);
   }
   
   public static String post(String url, String postJson) {
       CloseableHttpClient client = getHttpClient();
       HttpPost httpPost = new HttpPost(url);
       String content = null;
       CloseableHttpResponse response = null;
       try {

           StringEntity postEntity = new StringEntity(postJson.toString(), CHARSET_UTF8);
           postEntity.setContentEncoding("UTF-8");
           postEntity.setContentType("application/json");
           httpPost.setEntity(postEntity);
           
           response = client.execute(httpPost);
           if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
               HttpEntity entity = response.getEntity();
               
               content = EntityUtils.toString(entity, CHARSET_UTF8);

               EntityUtils.consume(entity);
           }
           
       }catch (Exception e) {
           logger.error("Exception when load "+url, e);
           
       } finally {
           httpPost.abort();       
           
           if (response != null) {
               try {
                   response.close();
               } catch (IOException ioe) {
                   logger.error("response close error:", ioe);
               }
           }
       }
       return content;
   
   }
   
   public static String get(String url) {
       CloseableHttpClient client = getHttpClient();
       HttpGet get = new HttpGet(url);
       String content = null;
       CloseableHttpResponse response = null;
       try {
           response = client.execute(get);
           if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
               HttpEntity entity = response.getEntity();
               
               content = EntityUtils.toString(entity, CHARSET_UTF8);
               EntityUtils.consume(entity);
           }
           
       }catch (Exception e) {
           logger.error("Exception when load "+url, e);
           
       } finally {
           get.abort();       
           
           if (response != null) {
               try {
                   response.close();
               } catch (IOException ioe) {
                   logger.error("response close error:", ioe);
               }
           }
       }
       return content;
   }
   
   public static void main(String[] args) {
       String response = get("http://www.baidu.com");
       
       logger.info("response:{}", response);
   }
}
